<html>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<head>
<title>Chapter 15</title>
<link rel="STYLESHEET" type="text/css" href="images/style.css">
<link rel="STYLESHEET" type="text/css" href="images/docsafari.css">
</head>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/team.gif" width="60" height="17" border="0" align="absmiddle"  alt="Team BBL"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=app03lev1sec14.html><img src="images/prev.gif" width="60" height="17" border="0" align="absmiddle" alt="Previous Page"></a>
<a href=app03lev1sec16.html><img src="images/next.gif" width="60" height="17" border="0" align="absmiddle" alt="Next Page"></a>
</div></td></tr></table>
<br><table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td valign="top"><a name="app03lev1sec15"></a>
<h3 class="docSection1Title">Chapter 15</h3>
<p class="docText"></P>
<P><table border="0" cellspacing="16" cellpadding="0"><tr valign="top"><TD align="right" class="docText" width="50"><a name="ch15qa1q1a1"></a><B><a class="docLink" href="ch15lev1sec12.html#ch15qa1q1">15.1</a></b></TD><td><p class="docText"><a name="idd1e118232"></a><a name="idd1e118235"></a><a name="idd1e118240"></a><a name="idd1e118245"></a><a name="idd1e118250"></a><a name="idd1e118253"></a><a name="idd1e118258"></a><a name="idd1e118263"></a><a name="idd1e118268"></a><a name="idd1e118273"></a>If the write end of the pipe is never closed, the reader never sees an end of file. The pager program blocks forever reading from its standard input.</P></TD></TR><tr valign="top"><TD align="right" class="docText" width="50"><a name="ch15qa1q2a2"></a><b><a class="docLink" href="ch15lev1sec12.html#ch15qa1q2">15.2</a></b></TD><TD><p class="docText">The parent terminates right after writing the last line to the pipe. The read end of the pipe is automatically closed when the parent terminates. But the parent is probably running ahead of the child by one pipe buffer, since the child (the pager program) is waiting for us to look at a page of output. If we're running a shell, such as the Korn shell, with interactive command-line editing enabled, the shell probably changes the terminal mode when our parent terminates and the shell prints a prompt. This undoubtedly interferes with the pager program, which has also modified the terminal mode. (Most pager programs set the terminal to noncanonical mode when awaiting input to proceed to the next page.)</P></td></TR><TR valign="top"><td align="right" class="docText" width="50"><a name="ch15qa1q3a3"></a><B><a class="docLink" href="ch15lev1sec12.html#ch15qa1q3">15.3</a></b></TD><td><p class="docText">The <tt>popen</tt> function returns a file pointer because the shell is executed. But the shell can't execute the nonexistent command, so it prints</p>
<pre>
      sh: line 1: ./a.out: No such file or directory
</pre><br>

<p class="docText">on the standard error and terminates with an exit status of 127. <tt>pclose</tt> returns the termination status of the command as it is returned by <tt>waitpid</tt>.</p></TD></tr><TR valign="top"><td align="right" class="docText" width="50"><a name="ch15qa1q4a4"></a><B><a class="docLink" href="ch15lev1sec12.html#ch15qa1q4">15.4</a></b></td><td><p class="docText">When the parent terminates, look at its termination status with the shell. For the Bourne shell, Bourne-again shell, and Korn shell, the command is <tt>echo $?</tt>. The number printed is 128 plus the signal number.</p></td></tr><tr valign="top"><td align="right" class="docText" width="50"><a name="ch15qa1q5a5"></a><b><a class="docLink" href="ch15lev1sec12.html#ch15qa1q5">15.5</a></b></td><td><p class="docText">First add the declaration</p>
<pre>
   FILE   *fpin, *fpout;
</pre><br>

<p class="docText">Then use <tt>fdopen</tt> to associate the pipe descriptors with a standard I/O stream, and set the streams to be line buffered. Do this before the <tt>while</tt> loop that reads from standard input:</p>
<pre>
    if ((fpin = fdopen(fd2[0], "r")) == NULL)
        err_sys("fdopen error");
    if ((fpout = fdopen(fd1[1], "w")) == NULL)
        err_sys("fdopen error");
    if (setvbuf(fpin, NULL, _IOLBF, 0) &lt; 0)
        err_sys("setvbuf error");
    if (setvbuf(fpout, NULL, _IOLBF, 0) &lt; 0)
        err_sys("setvbuf error");
</pre><br>

<p class="docText">The <tt>write</tt> and <tt>read</tt> in the <tt>while</tt> loop are replaced with</p>
<pre>
     if (fputs(line, fpout) == EOF)
         err_sys("fputs error to pipe");
     if (fgets(line, MAXLINE, fpin) == NULL) {
         err_msg("child closed pipe");
         break;
     }
</pre><br>
</td></TR><TR valign="top"><td align="right" class="docText" width="50"><a name="ch15qa1q6a6"></a><B><a class="docLink" href="ch15lev1sec12.html#ch15qa1q6">15.6</a></b></TD><TD><p class="docText"><a name="idd1e118498"></a><a name="idd1e118503"></a><a name="idd1e118508"></a><a name="idd1e118513"></a><a name="idd1e118518"></a><a name="idd1e118523"></a><a name="idd1e118528"></a><a name="idd1e118533"></a><a name="idd1e118538"></a><a name="idd1e118543"></a><a name="idd1e118548"></a><a name="idd1e118553"></a><a name="idd1e118558"></a><a name="idd1e118561"></a><a name="idd1e118566"></a><a name="idd1e118571"></a>The <tt>system</tt> function calls <tt>wait</tt>, and the first child to terminate is the child generated by <tt>popen</tt>. Since that's not the child that <tt>system</tt> created, it calls <tt>wait</tt> again and blocks until the <tt>sleep</tt> is done. Then <tt>system</tt> returns. When <tt>pclose</tt> calls <tt>wait</tt>, an error is returned, since there are no more children to <tt>wait</tt> for. Then <tt>pclose</tt> returns an error.</p></TD></TR><TR valign="top"><td align="right" class="docText" width="50"><a name="ch15qa1q7a7"></a><B><a class="docLink" href="ch15lev1sec12.html#ch15qa1q7">15.7</a></b></td><TD><p class="docText">The <tt>select</tt> function indicates that the descriptor is readable. When we call <tt>read</tt> after all the data has been read, it returns 0 to indicate the end of file. But with <tt>poll</tt> (assuming a STREAMS-based pipe), the <tt>POLLHUP</tt> event is returned, and this event may be returned while there is still data to be read. Once we have read all the data, however, <tt>read</tt> returns 0 to indicate the end of file. After all the data has been read, the <tt>POLLIN</tt> event is not returned, even though we need to issue a <tt>read</tt> to receive the end-of-file notification (the return of 0).</P>
<p class="docText">With an output descriptor that refers to a pipe that has been closed by the reader, <tt>select</tt> indicates that the descriptor is writable. But when we call <tt>write</tt>, the <tt>SIGPIPE</tt> signal is generated. If we either ignore this signal or return from its signal handler, <tt>write</tt> returns an error of <tt>EPIPE</tt>. With <tt>poll</tt>, however, if the pipe is STREAMS based, <tt>poll</tt> returns with a <tt>POLLHUP</tt> event for the descriptor.</P></td></TR><TR valign="top"><td align="right" class="docText" width="50"><a name="ch15qa1q8a8"></a><B><a class="docLink" href="ch15lev1sec12.html#ch15qa1q8">15.8</a></b></TD><td><p class="docText">Anything written by the child to standard error appears wherever the parent's standard error would appear. To send standard error back to the parent, include the shell redirection <tt>2&gt;&amp;1</tt> in the <span class="docEmphasis">cmdstring</span>.</p></td></tr><TR valign="top"><td align="right" class="docText" width="50"><a name="ch15qa1q9a9"></a><B><a class="docLink" href="ch15lev1sec12.html#ch15qa1q9">15.9</a></b></td><TD><p class="docText">The <tt>popen</tt> function <tt>fork</tt>s a child, and the child executes the shell. The shell in turn calls <tt>fork</tt>, and the child of the shell executes the command string. When <span class="docEmphasis">cmdstring</span> terminates, the shell is waiting for this to happen. The shell then exits, which is what the <tt>waitpid</tt> in <tt>pclose</tt> is waiting for.</p></td></tr><tr valign="top"><td align="right" class="docText" width="50"><a name="ch15qa1q10a10"></a><b><a class="docLink" href="ch15lev1sec12.html#ch15qa1q10">15.10</a></b></td><td><p class="docText">The trick is to <tt>open</tt> the FIFO twice: once for reading and once for writing. We never use the descriptor that is opened for writing, but leaving that descriptor open prevents an end of file from being generated when the number of clients goes from 1 to 0. Opening the FIFO twice requires some care, as a nonblocking <tt>open</tt> is required. We have to do a nonblocking, read-only <tt>open</tt> first, followed by a blocking <tt>open</tt> for write-only. (If we tried a nonblocking <tt>open</tt> for write-only first, it would return an error.) We then turn off nonblocking for the read descriptor. <a class="docLink" href="#app03fig18">Figure C.18</a> shows the code for this.</p>
<a name="app03fig18"></a>
<h5 class="docExampleTitle">Figure C.18. Opening a FIFO for reading and writing, without blocking</h5>
<pre>
#include "apue.h"
#include &lt;fcntl.h&gt;

#define FIFO    "temp.fifo"

int
main(void)
{
    int    fdread, fdwrite;

    unlink(FIFO);
    if (mkfifo(FIFO, FILE_MODE) &lt; 0)
        err_sys("mkfifo error");
    if ((fdread = open(FIFO, O_RDONLY | O_NONBLOCK)) &lt; 0)
        err_sys("open error for reading");
    if ((fdwrite = open(FIFO, O_WRONLY)) &lt; 0)
        err_sys("open error for writing");
    clr_fl(fdread, O_NONBLOCK);
    exit(0);
}
</pre><br>


</td></tr><tr valign="top"><td align="right" class="docText" width="50"><a name="ch15qa1q11a11"></a><b><a class="docLink" href="ch15lev1sec12.html#ch15qa1q11">15.11</a></b></TD><TD><p class="docText">Randomly reading a message from an active queue would interfere with the clientserver protocol, as either a client request or a server's response would be lost. To read the queue, all that is needed is for the process to know the identifier for the queue and for the queue to allow world-read access.</p></TD></TR><TR valign="top"><td align="right" class="docText" width="50"><a name="ch15qa1q13a13"></a><B><a class="docLink" href="ch15lev1sec12.html#ch15qa1q13">15.13</a></b></TD><TD><p class="docText">We never store actual addresses in a shared memory segment, since it's possible for the server and all the clients to attach the segment at different addresses. Instead, when a linked list is built in a shared memory segment, the list pointers should be stored as offsets to other objects in the shared memory segment. These offsets are formed by subtracting the start of the shared memory segment from the actual address of the object.</p></TD></tr><TR valign="top"><TD align="right" class="docText" width="50"><a name="ch15qa1q14a14"></a><B><a class="docLink" href="ch15lev1sec12.html#ch15qa1q14">15.14</a></b></td><TD><p class="docText"><a class="docLink" href="#app03fig19">Figure C.19</a> shows the relevant events.</P>
<a name="app03fig19"></a><p><table cellspacing="0" class="allBorders" border="1" RULES="groups" cellpadding="5"><caption><H5 class="docTableTitle">figure C.19. Alternation between parent and child in <a class="docLink" href="ch15lev1sec9.html#ch15fig33">Figure 15.33</a></H5></caption><colgroup><col width="80"><col width="80"><col width="100"><col width="80"><col width="160"></colgroup><thead><tr><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="top"><p class="docText"><span class="docEmphRoman">Parent <tt>i</tt> set to</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="top"><p class="docText"><span class="docEmphRoman">Child <tt>i</tt> set to</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="top"><p class="docText"><span class="docEmphRoman">Shared value set to</span></p></th><th class="rightBorder bottomBorder thead" scope="col" align="center" valign="top"><p class="docText"><span class="docEmphRoman"><tt>update</tt> returns</span></P></th><th class="bottomBorder thead" scope="col" align="center" valign="middle"><p class="docText"><span class="docEmphRoman">Comment</span></p></th></TR></thead><tr><TD class="rightBorder" align="center">&nbsp;</td><td class="rightBorder" align="center">&nbsp;</td><td class="rightBorder" align="center" valign="top"><p class="docText">0</p></td><td class="rightBorder" align="center">&nbsp;</td><td class="docTableCell" align="left" valign="top"><p class="docText">initialized by <tt>mmap</tt>
</p></td></tr><tr><td class="rightBorder" align="center">&nbsp;</td><td class="rightBorder" align="center" valign="top"><p class="docText">1</p></TD><TD class="rightBorder" align="center">&nbsp;</td><TD class="rightBorder" align="center">&nbsp;</TD><TD class="docTableCell" align="left" valign="top"><p class="docText">child runs first, then is blocked 0 parent runs</p></TD></TR><TR><td class="rightBorder" align="center" valign="top"><p class="docText">0</P></td><TD class="rightBorder" align="center">&nbsp;</TD><TD class="rightBorder" align="center">&nbsp;</td><TD class="rightBorder" align="center">&nbsp;</TD><td class="docTableCell" align="left" valign="top"><p class="docText">parent runs</P></TD></tr><tr><td class="rightBorder" align="center">&nbsp;</td><TD class="rightBorder" align="center">&nbsp;</td><TD class="rightBorder" align="center" valign="top"><p class="docText">1</p></TD><td class="rightBorder" align="center">&nbsp;</td><td class="docTableCell" align="center">&nbsp;</td></tr><tr><td class="rightBorder" align="center">&nbsp;</td><td class="rightBorder" align="center">&nbsp;</td><td class="rightBorder" align="center">&nbsp;</td><td class="rightBorder" align="center" valign="top"><p class="docText">0</p></td><td class="docTableCell" align="left" valign="top"><p class="docText">then parent is blocked</p></TD></TR><tr><TD class="rightBorder" align="center">&nbsp;</TD><TD class="rightBorder" align="center">&nbsp;</td><TD class="rightBorder" align="center" valign="top"><p class="docText">2</P></TD><td class="rightBorder" align="center">&nbsp;</TD><td class="docTableCell" align="left" valign="top"><p class="docText">child resumes</P></TD></TR><tr><TD class="rightBorder" align="center">&nbsp;</TD><td class="rightBorder" align="center">&nbsp;</TD><TD class="rightBorder" align="center">&nbsp;</td><td class="rightBorder" align="center" valign="top"><p class="docText">1</p></td><TD class="docTableCell" align="center">&nbsp;</td></TR><tr><TD class="rightBorder" align="center">&nbsp;</td><td class="rightBorder" align="center" valign="top"><p class="docText">3</p></td><td class="rightBorder" align="center">&nbsp;</td><td class="rightBorder" align="center">&nbsp;</td><td class="docTableCell" align="left" valign="top"><p class="docText">then child is blocked</p></td></tr><tr><td class="rightBorder" align="center" valign="top"><p class="docText">2</p></td><td class="rightBorder" align="center">&nbsp;</TD><TD class="rightBorder" align="center">&nbsp;</td><TD class="rightBorder" align="center">&nbsp;</TD><TD class="docTableCell" align="left" valign="top"><p class="docText">parent resumes</p></TD></TR><TR><td class="rightBorder" align="center">&nbsp;</TD><td class="rightBorder" align="center">&nbsp;</TD><TD class="rightBorder" align="center" valign="top"><p class="docText">3</P></td><TD class="rightBorder" align="center">&nbsp;</TD><td class="docTableCell" align="center">&nbsp;</TD></TR><tr><td class="rightBorder" align="center">&nbsp;</td><td class="rightBorder" align="center">&nbsp;</TD><td class="rightBorder" align="center">&nbsp;</TD><td class="rightBorder" align="center" valign="top"><p class="docText">2</P></td><td class="docTableCell" align="left" valign="top"><p class="docText">then parent is blocked</p></td></tr><tr><td class="rightBorder" align="center">&nbsp;</td><td class="rightBorder" align="center">&nbsp;</td><td class="rightBorder" align="center" valign="top"><p class="docText">4</p></td><td class="rightBorder" align="center">&nbsp;</td><td class="docTableCell" align="center">&nbsp;</td></TR><TR><td class="rightBorder" align="center">&nbsp;</TD><TD class="rightBorder" align="center">&nbsp;</TD><td class="rightBorder" align="center">&nbsp;</TD><TD class="rightBorder" align="center" valign="top"><p class="docText">3</P></td><TD class="docTableCell" align="center">&nbsp;</td></TR><TR><TD class="rightBorder" align="center">&nbsp;</td><TD class="rightBorder" align="center" valign="top"><p class="docText">5</P></td><TD class="rightBorder" align="center">&nbsp;</TD><td class="rightBorder" align="center">&nbsp;</td><td class="docTableCell" align="left" valign="top"><p class="docText">then child is blocked</p></TD></tr><TR><td class="rightBorder" align="center" valign="top"><p class="docText">4</P></td><td class="rightBorder" align="center">&nbsp;</td><td class="rightBorder" align="center">&nbsp;</td><td class="rightBorder" align="center">&nbsp;</td><td class="docTableCell" align="left" valign="top"><p class="docText">parent resumes</p></td></tr></table></p><br></td></tr></table></p>

<a href="17021535.html"><img src="images/pixel.gif" alt="" width="1" height="1" border="0"></a><ul></UL></TD></tr></table>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/team.gif" width="60" height="17" border="0" align="absmiddle"  alt="Team BBL"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=app03lev1sec14.html><img src="images/prev.gif" width="60" height="17" border="0" align="absmiddle" alt="Previous Page"></a>
<a href=app03lev1sec16.html><img src="images/next.gif" width="60" height="17" border="0" align="absmiddle" alt="Next Page"></a>
</div></td></tr></table>
</body></html><br>
<table width="100%" cellspacing="0" cellpadding="0"
style="margin-top: 0pt; border-collapse: collapse;"> 
<tr> <td align="right" style="background-color=white; border-top: 1px solid gray;"> 
<a href="http://www.zipghost.com/" target="_blank" style="font-family: Tahoma, Verdana;
 font-size: 11px; text-decoration: none;">The CHM file was converted to HTM by Trial version of <b>ChmD<!--99-->ecompiler</b>.</a>
</TD>
</TR><tr>
<td align="right" style="background-color=white; "> 
<a href="http://www.etextwizard.com/download/cd/cdsetup.exe" target="_blank" style="font-family: Tahoma, Verdana;
 font-size: 11px; text-decoration: none;">Download <b>ChmDec<!--99-->ompiler</b> at: http://www.zipghost.com</a>
</TD></tr></table>
